/*
 *  Copyright 2011 yura.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *  under the License.
 */
package org.opu.db_vdumper.ui.component.area;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JComponent;
import org.opu.db_vdumper.ui.component.area.model.CanvesModel;
import org.opu.db_vdumper.ui.component.area.model.DraggebleListener;
import org.opu.db_vdumper.ui.View;
import org.opu.db_vdumper.ui.ViewFactory;
import org.opu.db_vdumper.ui.component.tabel.ArrowMethod;
import org.opu.db_vdumper.ui.component.tabel.TabelViewMethod;
import org.opu.db_vdumper.ui.component.tabel.models.ArrowModel;
import org.opu.db_vdumper.ui.component.tabel.models.TableModel;
import org.opu.db_vdumper.ui.component.tabel.views.ArrowView;
import org.opu.db_vdumper.ui.component.tabel.views.TableView;
import org.opu.db_vdumper.util.Logger;

/**
 *
 * @author Potochnak Yana
 */
public class Canves extends JComponent implements View, TmplDrawer {

    private CanvesModel model;
    private DraggebleListener listener;
    private Shape tmp = null;

    private boolean canAdd = false;
    private boolean drawCell = false;

    private CellDrawingProperties drawingProperties = new CellDrawingProperties();

    public Canves(CanvesModel model) {
        this.model = model;
        this.listener = new DraggebleListener(this.model);
        setDoubleBuffered(true);
        setLayout(new SmartLayout());
        setBackground(Color.WHITE);
        addListener(Canves.this);
    }

    @Override
    protected void addImpl(Component comp, Object constraints, int index) {
        if (!canAdd) {
            throw new RuntimeException("Add component to canvas can only it self!");
        }

        addListener(comp);
        super.addImpl(comp, constraints, index);
    }

    private void addListener(Component comp) {
        comp.addMouseListener((MouseListener) listener);
        
        if (comp instanceof Canves) {
            // move with cursor ...
        } else {
            comp.addMouseMotionListener((MouseMotionListener) listener);
        }
    }

    @Override
    public void setTmp(Shape shape) {
        tmp = shape;
    }

    @Override
    public void deleteTmp() {
        tmp = null;
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        Color color = g2.getColor();
        Stroke stroke = g2.getStroke();

        if (drawCell) {
            CellDrawingProperties prop = getDrawingProperties();
            Dimension s = getSize();
            g2.setColor(prop.getColor());
            Stroke sk = prop.getStroke();

            if (sk != null) {
                g2.setStroke(sk);
            }

            for (int i = prop.getWidthDistantion(); i < s.width; i += 20) {
                g2.drawLine(i, 0, i, s.height);
                for (int j = prop.getHeightDistantion(); j < s.height; j += 20) {
                    g2.drawLine(0, j, s.width, j);
                }
            }

            if (sk != null) {
                g2.setStroke(stroke);
            }

            g2.setColor(color);
        }

        if (tmp != null) {
            g2.setStroke(new BasicStroke(3.0f, 0, 0, 2.0f, new float[]{10.0f}, 0.0f));
            g2.setColor(Color.LIGHT_GRAY);
            g2.draw(tmp);
            g2.setColor(color);
            g2.setStroke(stroke);
        }
    }

    @Override
    public synchronized void reset() {
        Logger.getInstance().info(this, "init component");
        //remove and adding all components from model.
        setCanAdd(true);
        removeAll();
        SmartLayout.__Killme = 10;

        if (model != null){
            List<TableModel> tables = model.getTables();
            List<TableView> tvs = new ArrayList<TableView>(tables.size());

            TabelViewMethod tmod = ViewFactory.getInstance().getTabelViewMethod();
            for (TableModel tm : tables) {
                TableView v = tmod.getTableView(tm);
                tm.addViews(v);
                tvs.add((TableView) add(v));
            }

            ArrowMethod amethod = ViewFactory.getInstance().getArrowMethod();
            for (ArrowModel am : model.getArrows()) {
                am.addViews((ArrowView) add(amethod.getArrowView(am, tvs)));
            }
        }
        
        revalidate();
        repaint();
        setCanAdd(false);
    }

    protected boolean isCanAdd() {
        return canAdd;
    }

    protected void setCanAdd(boolean canAdd) {
        this.canAdd = canAdd;
    }

    @Override
    public boolean isDrawCell() {
        return drawCell;
    }

    @Override
    public void setDrawCell(boolean drawCell) {
        this.drawCell = drawCell;
    }

    @Override
    public CellDrawingProperties getDrawingProperties() {
        if (drawingProperties == null) {
            drawingProperties = new CellDrawingProperties();
        }

        return drawingProperties;
    }

    @Override
    public void setDrawingProperties(CellDrawingProperties drawingProperties) {
        this.drawingProperties = drawingProperties;
    }

    public CanvesModel getModel() {
        return model;
    }

    public void setModel(CanvesModel model) {
        this.model = model;
        this.listener.setCanvesModel(this.model);
        Logger.getInstance().info(this, "Change canves model to " + model);
        reset();
    }
}
